# exploratory_analysis.py - 修复版本
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from config import VISUALIZATION_CONFIG


class ExploratoryAnalysis:
    def __init__(self, df):
        self.df = df
        self.setup_visualization()

    def setup_visualization(self):
        """设置可视化参数"""
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        plt.rcParams['figure.figsize'] = VISUALIZATION_CONFIG['figure_size']
        plt.rcParams['font.size'] = VISUALIZATION_CONFIG['font_size']

    def basic_statistics(self):
        """输出基本统计信息"""
        print("\n=== 基本统计信息 ===")
        print(f"总订单数: {len(self.df):,}")
        print(f"总用户数: {self.df['用户ID'].nunique():,}")
        print(f"总商家数: {self.df['商家ID'].nunique():,}")

        if '实付金额' in self.df.columns:
            print(f"总销售额: {self.df['实付金额'].sum():,.2f}元")
            print(f"平均订单金额: {self.df['实付金额'].mean():.2f}元")
            print(f"订单金额中位数: {self.df['实付金额'].median():.2f}元")

        if '购买数量' in self.df.columns:
            print(f"平均购买数量: {self.df['购买数量'].mean():.2f}")

        if '使用状态' in self.df.columns:
            # 计算优惠券使用率（只考虑已领取的用户）
            coupon_users = self.df[self.df['使用状态'].isin([0, 1])]
            if len(coupon_users) > 0:
                usage_rate = len(coupon_users[coupon_users['使用状态'] == 1]) / len(coupon_users)
                print(f"优惠券使用率: {usage_rate:.2%}")

    def create_consumption_dashboard(self):
        """创建消费行为分析仪表板"""
        print("\n=== 消费行为分析可视化 ===")

        fig = plt.figure(figsize=(20, 16))

        # 1. 实付金额分布
        ax1 = plt.subplot(3, 3, 1)
        if '实付金额' in self.df.columns:
            # 移除负值
            positive_amounts = self.df[self.df['实付金额'] > 0]['实付金额']
            plt.hist(positive_amounts, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
            plt.title('实付金额分布')
            plt.xlabel('实付金额(元)')
            plt.ylabel('频次')

        # 2. 各省份消费金额分布
        ax2 = plt.subplot(3, 3, 2)
        if '省份' in self.df.columns and '实付金额' in self.df.columns:
            province_consumption = self.df.groupby('省份')['实付金额'].sum().sort_values(ascending=False)
            province_consumption.head(10).plot(kind='bar', color='lightcoral')
            plt.title('各省份消费金额TOP10')
            plt.xticks(rotation=45)

        # 3. 购买数量分布
        ax3 = plt.subplot(3, 3, 3)
        if '购买数量' in self.df.columns:
            quantity_dist = self.df['购买数量'].value_counts().head(10)
            quantity_dist.plot(kind='bar', color='lightgreen')
            plt.title('购买数量分布TOP10')
            plt.xlabel('购买数量')
            plt.ylabel('订单数')

        # 4. 邮费支付情况
        ax4 = plt.subplot(3, 3, 4)
        if '邮费' in self.df.columns:
            shipping_fee_counts = self.df['邮费'].value_counts().head(8)
            plt.pie(shipping_fee_counts.values, labels=shipping_fee_counts.index, autopct='%1.1f%%')
            plt.title('邮费金额分布')

        # 5. 优惠券使用情况 - 完全重写
        ax5 = plt.subplot(3, 3, 5)
        if '使用状态' in self.df.columns:
            # 统计使用状态
            usage_counts = self.df['使用状态'].value_counts()

            # 创建标签映射
            label_map = {1: '已使用', 0: '未使用'}
            labels = []
            sizes = []

            for status, count in usage_counts.items():
                if status in label_map:
                    labels.append(label_map[status])
                    sizes.append(count)
                else:
                    # 处理其他状态
                    labels.append(f'状态{status}')
                    sizes.append(count)

            # 绘制饼图
            if sizes:
                plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90)
                plt.title('优惠券使用情况')
            else:
                plt.text(0.5, 0.5, '无优惠券使用数据', ha='center', va='center', transform=plt.gca().transAxes)
                plt.title('优惠券使用情况')

        # 6. 用户消费频次分布
        ax6 = plt.subplot(3, 3, 6)
        if '用户ID' in self.df.columns:
            user_frequency = self.df['用户ID'].value_counts()
            user_frequency.hist(bins=20, alpha=0.7, color='orange')
            plt.title('用户消费频次分布')
            plt.xlabel('消费次数')
            plt.ylabel('用户数')

        # 7. 商家销售分布
        ax7 = plt.subplot(3, 3, 7)
        if '商家ID' in self.df.columns and '实付金额' in self.df.columns:
            merchant_sales = self.df.groupby('商家ID')['实付金额'].sum().nlargest(10)
            merchant_sales.plot(kind='bar', color='purple', alpha=0.7)
            plt.title('商家销售额TOP10')
            plt.xticks(rotation=45)

        # 8. 月度消费趋势
        ax8 = plt.subplot(3, 3, 8)
        if '付款日期' in self.df.columns and '实付金额' in self.df.columns:
            try:
                # 确保日期是datetime类型
                if not pd.api.types.is_datetime64_any_dtype(self.df['付款日期']):
                    self.df['付款日期'] = pd.to_datetime(self.df['付款日期'], errors='coerce')

                # 移除无效日期
                valid_dates = self.df[self.df['付款日期'].notna()]
                if len(valid_dates) > 0:
                    monthly_sales = valid_dates.set_index('付款日期')['实付金额'].resample('M').sum()
                    monthly_sales.plot(kind='line', marker='o', color='red')
                    plt.title('月度消费趋势')
                    plt.xlabel('月份')
                    plt.ylabel('销售额')
                else:
                    plt.text(0.5, 0.5, '无有效日期数据', ha='center', va='center', transform=plt.gca().transAxes)
                    plt.title('月度消费趋势')
            except Exception as e:
                plt.text(0.5, 0.5, f'日期处理错误: {e}', ha='center', va='center', transform=plt.gca().transAxes)
                plt.title('月度消费趋势')

        # 9. 城市消费热力图
        ax9 = plt.subplot(3, 3, 9)
        if '城市' in self.df.columns and '实付金额' in self.df.columns:
            city_sales = self.df.groupby('城市')['实付金额'].sum().nlargest(15)
            city_sales.plot(kind='barh', color='teal', alpha=0.7)
            plt.title('城市销售额TOP15')

        plt.tight_layout()
        plt.show()

        return fig

    def correlation_analysis(self):
        """相关性分析"""
        print("\n=== 相关性分析 ===")

        # 选择数值字段
        numeric_cols = self.df.select_dtypes(include=[np.number]).columns

        if len(numeric_cols) > 1:
            # 计算相关系数矩阵
            corr_matrix = self.df[numeric_cols].corr()

            plt.figure(figsize=(10, 8))
            sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0,
                        square=True, linewidths=0.5, fmt='.2f')
            plt.title('数值字段相关性热力图')
            plt.tight_layout()
            plt.show()

            # 输出强相关性对
            strong_corr_pairs = []
            for i in range(len(corr_matrix.columns)):
                for j in range(i + 1, len(corr_matrix.columns)):
                    corr_value = corr_matrix.iloc[i, j]
                    if abs(corr_value) > 0.5 and not pd.isna(corr_value):
                        strong_corr_pairs.append((
                            corr_matrix.columns[i],
                            corr_matrix.columns[j],
                            corr_value
                        ))

            if strong_corr_pairs:
                print("\n强相关性字段对 (|r| > 0.5):")
                for col1, col2, corr in strong_corr_pairs:
                    print(f"  {col1} - {col2}: {corr:.3f}")
            else:
                print("没有发现强相关性字段对 (|r| > 0.5)")
        else:
            print("数值字段不足，无法进行相关性分析")

    def perform_complete_analysis(self):
        """执行完整的探索性分析"""
        try:
            self.basic_statistics()
            self.create_consumption_dashboard()
            self.correlation_analysis()
        except Exception as e:
            print(f"探索性分析过程中出现错误: {e}")
            import traceback
            traceback.print_exc()